package cn.skylark.wcm.common.jwt;

import cn.skylark.wcm.common.redis.RedisUtils;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * JWT鉴权过滤器
 *
 * @author chuhl
 * @since 2018-1-11
 */
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    /**
     * 需要验证访问链接
     */
    private final String[] protectUrlPattern;
    /**
     * 匹配器
     */
    private static final PathMatcher pathMatcher = new AntPathMatcher();
    /**
     * REDIS服务器调用初始化接口
     */
    private final RedisUtils redisUtils;
    public JwtAuthenticationFilter(String[] protectUrlPattern,RedisUtils redisUtils) {
        this.protectUrlPattern = protectUrlPattern;
        this.redisUtils = redisUtils;
    }

    /**
     * 继承过滤器处理
     *
     * 1：获取验证访问路径
     * 2：访问方式为OPTIONS跳过验证处理，次访问方式一般为跨域请求
     * 3：运用匹配器进行请求访问路径匹配处理
     * 4：匹配成功，进入TOKEN验证
     * 5：根据TOKEN验证返回结果，判断是否进行正式的访问路径的访问
     *
     * @param request request请求
     * @param response reponse返回请求
     * @param filterChain 过滤器
     * @throws ServletException Servlet异常
     * @throws IOException IO异常
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        JwtUtil jwtUtil = new JwtUtil();
        Map<String , java.lang.Object> retMap;
        for (String urlPattern : protectUrlPattern) {
            if(!request.getMethod().equals( "OPTIONS" )){
                if (pathMatcher.match( urlPattern, request.getServletPath() )) {
                    retMap = jwtUtil.validateToken( request ,redisUtils);
                    request = (HttpServletRequest)retMap.get( "request" );
                    response.setStatus( (Integer) retMap .get( "code" ) );
                    if((Integer) retMap .get( "code" ) == 401 || (Integer) retMap .get( "code" ) == 417 || (Integer) retMap .get( "code" ) == 403) {
                        response.setHeader("Access-Control-Allow-Origin","*");
                        response.sendError( (Integer) retMap.get( "code" ) );
                        return;
                    }
                    break;
                }
            }
        }
        filterChain.doFilter(request, response);
    }
}
